#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdio>
#include <queue>

typedef long long ll;
template <typename T>
inline void read(T &x) {
  x = 0;
  bool flag = false;
  short ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') flag = true;
    ch = getchar();
  }
  while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ '0'), ch = getchar();
  if (flag) x = -x;
}

const int N = 5e5 + 5, M = 3e6 + 5;
int n, m, p[N], fa[N], vis[N], cur;
int e_cnt, heads[N];
bool jud[N];
ll mxval, mnval, zp[N];
std::queue<int> q;

struct Edge {
  int v, nxt, w;
} e[M << 1];

inline void add(int u, int v, int w) {
  e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt, e[e_cnt].w = w;
}

inline void quit() {
  puts("NIE");
  exit(0);
}

struct Node {
  ll a, b;
  Node() {}
  Node(const ll &a, const ll &b) : a(a), b(b) {}
  inline Node operator-(const Node &rhs) const {
    return Node(a - rhs.a, b - rhs.b);
  }
} zt[N];

inline ll calc(int st, ll dt) {
  while (!q.empty()) q.pop();
  q.push(st);
  vis[st] = ++cur;
  zp[st] = dt;
  ll res = 0;
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    jud[x] = true;
    if (zp[x] < 0 || zp[x] > p[x]) quit();
    res += zp[x];
    for (int i = heads[x], v; i; i = e[i].nxt) {
      ll tmp = p[x] + p[v = e[i].v] - e[i].w - zp[x];
      if (vis[v] != cur) {
        vis[v] = cur, zp[v] = tmp;
        q.push(v);
      } else if (zp[v] != tmp)
        quit();
    }
  }
  return res;
}

inline void solve(int st) {
  while (!q.empty()) q.pop();
  q.push(st);
  vis[st] = ++cur;
  zt[st] = Node(1, 0);
  ll l = 0, r = p[st];
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    if (zt[x].a == 1) {
      l = std::max(l, -zt[x].b);
      r = std::min(r, p[x] - zt[x].b);
    } else {
      l = std::max(l, zt[x].b - p[x]);
      r = std::min(r, zt[x].b);
    }
    if (l > r) quit();
    for (int i = heads[x], v; i; i = e[i].nxt)
      if (vis[v = e[i].v] != cur) {
        fa[v] = x, vis[v] = cur;
        zt[v] = Node(0, p[x] + p[v] - e[i].w) - zt[x];
        q.push(v);
      } else if (v != fa[x]) {
        Node t = Node(0, p[x] + p[v] - e[i].w) - zt[x];
        if (zt[v].a != t.a) {
          ll tmp = (t.a == 1 ? zt[v].b - t.b : t.b - zt[v].b);
          if (tmp % 2 == 1) quit();
          else
            return tmp = calc(st, tmp / 2), mxval += tmp, mnval += tmp, void();
        } else if (zt[v].b != t.b)
          quit();
      }
  }
  ll v1 = calc(st, l), v2 = calc(st, r);
  mxval += std::max(v1, v2), mnval += std::min(v1, v2);
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#else
  freopen("P3544 [POI2012]BEZ-Minimalist Security.in", "r", stdin);
  freopen("P3544 [POI2012]BEZ-Minimalist Security.out", "w", stdout);
#endif
#endif

  read(n), read(m);
  for (int i = 1; i <= n; ++i) read(p[i]);
  for (int i = 1, u, v, w; i <= m; ++i) {
    read(u), read(v), read(w);
    add(u, v, w), add(v, u, w);
  }
  for (int i = 1; i <= n; ++i)
    if (!jud[i]) solve(i);
  printf("%lld %lld", mnval, mxval);
  return 0;
}